package middlewares

import (
	"errors"
	"fmt"
	"github.com/afex/hystrix-go/hystrix"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"time"
)

var CircuitBreakerName = "api_%s_circuit_breaker"
var f *os.File
var filename string

func checkFileIsExist(filename string) bool {
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		return false
	}
	return true
}
func CircuitBreakerWrapper(ctx *gin.Context) {
	name := fmt.Sprintf(CircuitBreakerName, ctx.Request.URL)
	hystrix.Do(name, func() error {
		ctx.Next()
		code := ctx.Writer.Status()
		if code != http.StatusOK {
			return errors.New(fmt.Sprintf("status code %d", code))
		}
		return nil

	}, func(err error) error {
		if err != nil {
			_, _ = io.WriteString(f, fmt.Sprintf("circuitBreaker and err is %s\n", err.Error()))
			fmt.Printf("circuitBreaker and err is %s\n", err.Error())
			//返回熔断错误信息
			ctx.JSON(http.StatusServiceUnavailable, gin.H{
				"msg": err.Error(),
			})
		}
		return nil
	})
}
func init() {
	day := time.Now().Format("2006-01-02")
	filename = "hystix.api_" + day + ".log"
	hystrix.ConfigureCommand(CircuitBreakerName, hystrix.CommandConfig{
		Timeout:                int(3 * time.Second),
		MaxConcurrentRequests:  10,                   //command 最大的并发量
		RequestVolumeThreshold: 100,                  //统计窗口10s内的请求数量 达到这个请求树才去判断是否开启熔断
		SleepWindow:            int(2 * time.Second), // 当熔断器打开后 sleepWindow 时间就是控制多久 再去尝试服务是否可用
		ErrorPercentThreshold:  20,                   //错误百分比 请求数量大于Request
	})
	if checkFileIsExist(filename) {
		f, _ = os.OpenFile(filename, os.O_APPEND, 0666)
	} else {
		f, _ = os.Create(filename)
	}
}
